using System;
using System.Collections.Generic;
using Headsight.BPMN2WF.BPMN.Model;
using Headsight.BPMN2WF.Transformation;

namespace Headsight.BPMN2WF.Testing.TestObjCtors
{
    /// <summary>
    /// <see cref="IBPMN2WFTransformations"/> <see cref="ITestObjCtor{T}"/>.
    /// </summary>
    public class BPMN2WFTransformations4TestingCtor : ITestObjCtor<IBPMN2WFTransformations>
    {
        private readonly IDictionary<BPMNFlowNode, IBPMN2WFTransformation> _dic;
        private readonly IDictionary<Type, Type> _dic2;
        private Type _default;

        public BPMN2WFTransformations4TestingCtor()
        {
            _dic = new Dictionary<BPMNFlowNode, IBPMN2WFTransformation>();
            _dic2 = new Dictionary<Type, Type>();

            _default = typeof (BPMN2WFTransformation_4TestingAssign);
        }

        public IBPMN2WFTransformations Create()
        {
            return new BPMN2WFTransformations4Testing(_dic2, _dic, _default);
        }

        public BPMN2WFTransformations4TestingCtor With(Type tElementType, Type bpmn2WfTransformationType)
        {
            _dic2.Add(tElementType, bpmn2WfTransformationType);

            return this;
        }

        public BPMN2WFTransformations4TestingCtor WithDefault(Type type)
        {
            _default = type;

            return this;
        }

        public BPMN2WFTransformations4TestingCtor With(BPMNFlowNode flowNode, IBPMN2WFTransformation bpmn2WfTransformation)
        {
            _dic[flowNode] = bpmn2WfTransformation;

            return this;
        }

        private class BPMN2WFTransformations4Testing : IBPMN2WFTransformations
        {
            private readonly IDictionary<Type, Type> _dicTypes;
            private readonly IDictionary<BPMNFlowNode, IBPMN2WFTransformation> _dicInstances;
            private readonly Type _default;

            public BPMN2WFTransformations4Testing(IDictionary<Type, Type> dicTypes, IDictionary<BPMNFlowNode, IBPMN2WFTransformation> dicInstances, Type @default)
            {
                _dicTypes = dicTypes;
                _dicInstances = dicInstances;
                _default = @default;
            }

            public IBPMN2WFTransformation Get(BPMNFlowNode flowNode)
            {
                if (_dicInstances.ContainsKey(flowNode))
                {
                    return _dicInstances[flowNode];
                }

                if (_dicTypes.ContainsKey(flowNode.TElement.GetType()))
                {
                    return (IBPMN2WFTransformation) Activator.CreateInstance(_dicTypes[flowNode.TElement.GetType()]);
                }

                return (IBPMN2WFTransformation) Activator.CreateInstance(_default);
            }
        }
    }
}